Header file floating_point.hpp

namespace type_safe
{
    template <typename FloatT>
    class floating_point;
    
    template <typename A, typename B>
    constexpr bool operator<(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    
    template <typename A, typename B>
    constexpr bool operator<(const A& a, const floating_point<B>& b);
    template <typename A, typename B>
    constexpr bool operator<(const floating_point<A>& a, const B& b);
    template <typename A, typename B>
    constexpr bool operator<=(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr bool operator<=(const A& a, const floating_point<B>& b);
    template <typename A, typename B>
    constexpr bool operator<=(const floating_point<A>& a, const B& b);
    template <typename A, typename B>
    constexpr bool operator>(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr bool operator>(const A& a, const floating_point<B>& b);
    template <typename A, typename B>
    constexpr bool operator>(const floating_point<A>& a, const B& b);
    template <typename A, typename B>
    constexpr bool operator>=(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr bool operator>=(const A& a, const floating_point<B>& b);
    template <typename A, typename B>
    constexpr bool operator>=(const floating_point<A>& a, const B& b);
    
    //=== Binary operations ===//
    template <typename A, typename B>
    constexpr 'hidden' operator+(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator+(const A& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator+(const floating_point<A>& a, const B& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator-(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator-(const A& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator-(const floating_point<A>& a, const B& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator*(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator*(const A& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator*(const floating_point<A>& a, const B& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator/(const floating_point<A>& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator/(const A& a, const floating_point<B>& b) noexcept;
    template <typename A, typename B>
    constexpr 'hidden' operator/(const floating_point<A>& a, const B& b) noexcept;
    
    template <typename Char, class CharTraits, typename FloatT>
    std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in, floating_point<FloatT>& f);
    
    template <typename Char, class CharTraits, typename FloatT>
    std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out, const floating_point<FloatT>& f);
}

namespace std
{
}

Class template type_safe::floating_point [types]

template <typename FloatT>
class floating_point
{
public:
    using floating_point_type = FloatT;
    
    template <typename T>
    constexpr floating_point(const T& val) noexcept;
    template <typename T>
    constexpr floating_point(const floating_point<T>& val) noexcept;
    
    template <typename T>
    floating_point& operator=(const T& val) noexcept;
    template <typename T>
    floating_point& operator=(const floating_point<T>& val) noexcept;
    
    constexpr operator floating_point_type() const noexcept;
    constexpr floating_point_type get() const noexcept;
    
    constexpr floating_point operator+() const noexcept;
    
    constexpr floating_point operator-() const noexcept;
    
    //=== Compound assignment ===//
    template <typename T>
    floating_point& operator+=(const floating_point<T>& other) noexcept;
    template <typename T>
    floating_point& operator+=(const T& other) noexcept;
    template <typename T>
    floating_point& operator-=(const floating_point<T>& other) noexcept;
    template <typename T>
    floating_point& operator-=(const T& other) noexcept;
    template <typename T>
    floating_point& operator*=(const floating_point<T>& other) noexcept;
    template <typename T>
    floating_point& operator*=(const T& other) noexcept;
    template <typename T>
    floating_point& operator/=(const floating_point<T>& other) noexcept;
    template <typename T>
    floating_point& operator/=(const T& other) noexcept;
};

A type safe floating point class.

It is a tiny, no overhead wrapper over a standard floating point type. It behaves exactly like the built-in types except it does not allow narrowing conversions.

Requires: FloatT must be a floating point type.

Notes: It intentionally does not provide equality or increment/decrement operators.

Function template type_safe::floating_point::floating_point

(1)  template <typename T>
     constexpr floating_point(const T& val) noexcept;

(2)  template <typename T>
     constexpr floating_point(const floating_point<T>& val) noexcept;

Effects: Initializes the floating point with the given value.

Notes: These functions do not participate in overload resolution, if T is not a floating point type safely convertible to this type.

Assignment operator type_safe::floating_point::operator=

(1)  template <typename T>
     floating_point& operator=(const T& val) noexcept;

(2)  template <typename T>
     floating_point& operator=(const floating_point<T>& val) noexcept;

Effects: Assigns the floating point the given value.

Notes: These functions do not participate in overload resolution, if T is not a floating point type safely convertible to this type.

Conversion operator type_safe::floating_point::operator floating_point_type

(1)  constexpr operator floating_point_type() const noexcept;

(2)  constexpr floating_point_type get() const noexcept;

Returns: The stored value as the native floating point type.

Operator type_safe::floating_point::operator+

constexpr floating_point operator+() const noexcept;

Returns: The value unchanged.

Operator type_safe::floating_point::operator-

constexpr floating_point operator-() const noexcept;

Returns: The negative value.

Compound assignment [types]

(1)  template <typename T>
     floating_point& operator+=(const floating_point<T>& other) noexcept;

(2)  template <typename T>
     floating_point& operator+=(const T& other) noexcept;

(3)  template <typename T>
     floating_point& operator-=(const floating_point<T>& other) noexcept;

(4)  template <typename T>
     floating_point& operator-=(const T& other) noexcept;

(5)  template <typename T>
     floating_point& operator*=(const floating_point<T>& other) noexcept;

(6)  template <typename T>
     floating_point& operator*=(const T& other) noexcept;

(7)  template <typename T>
     floating_point& operator/=(const floating_point<T>& other) noexcept;

(8)  template <typename T>
     floating_point& operator/=(const T& other) noexcept;

Effects: Same as the operation on the floating point type.

Notes: These functions do not participate in overload resolution, if T is not a floating point type safely convertible to this type.


Comparison operator type_safe::operator<

template <typename A, typename B>
constexpr bool operator<(const floating_point<A>& a, const floating_point<B>& b) noexcept;

Returns: The result of the comparison of the stored floating point value in the ts::floating_point. \notes These functions do not participate in overload resolution unless A and B are both floating point types. \group float_comp Comparison operators \module types

Comparison operator type_safe::operator<

(1)  template <typename A, typename B>
     constexpr bool operator<(const A& a, const floating_point<B>& b);

(2)  template <typename A, typename B>
     constexpr bool operator<(const floating_point<A>& a, const B& b);

(3)  template <typename A, typename B>
     constexpr bool operator<=(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(4)  template <typename A, typename B>
     constexpr bool operator<=(const A& a, const floating_point<B>& b);

(5)  template <typename A, typename B>
     constexpr bool operator<=(const floating_point<A>& a, const B& b);

(6)  template <typename A, typename B>
     constexpr bool operator>(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(7)  template <typename A, typename B>
     constexpr bool operator>(const A& a, const floating_point<B>& b);

(8)  template <typename A, typename B>
     constexpr bool operator>(const floating_point<A>& a, const B& b);

(9)  template <typename A, typename B>
     constexpr bool operator>=(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(10)  template <typename A, typename B>
     constexpr bool operator>=(const A& a, const floating_point<B>& b);

(11)  template <typename A, typename B>
     constexpr bool operator>=(const floating_point<A>& a, const B& b);

Binary operations [types]

(1)  template <typename A, typename B>
     constexpr 'hidden' operator+(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(2)  template <typename A, typename B>
     constexpr 'hidden' operator+(const A& a, const floating_point<B>& b) noexcept;

(3)  template <typename A, typename B>
     constexpr 'hidden' operator+(const floating_point<A>& a, const B& b) noexcept;

(4)  template <typename A, typename B>
     constexpr 'hidden' operator-(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(5)  template <typename A, typename B>
     constexpr 'hidden' operator-(const A& a, const floating_point<B>& b) noexcept;

(6)  template <typename A, typename B>
     constexpr 'hidden' operator-(const floating_point<A>& a, const B& b) noexcept;

(7)  template <typename A, typename B>
     constexpr 'hidden' operator*(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(8)  template <typename A, typename B>
     constexpr 'hidden' operator*(const A& a, const floating_point<B>& b) noexcept;

(9)  template <typename A, typename B>
     constexpr 'hidden' operator*(const floating_point<A>& a, const B& b) noexcept;

(10)  template <typename A, typename B>
     constexpr 'hidden' operator/(const floating_point<A>& a, const floating_point<B>& b) noexcept;

(11)  template <typename A, typename B>
     constexpr 'hidden' operator/(const A& a, const floating_point<B>& b) noexcept;

(12)  template <typename A, typename B>
     constexpr 'hidden' operator/(const floating_point<A>& a, const B& b) noexcept;

Returns: The result of the binary operation of the stored floating point value in the ts::floating_point. The type is a ts::floating_point of the bigger floating point type.

Notes: These functions do not participate in overload resolution, unless A and B are both floating point types.

Input operator type_safe::operator>>

template <typename Char, class CharTraits, typename FloatT>
std::basic_istream<Char, CharTraits>& operator>>(std::basic_istream<Char, CharTraits>& in, floating_point<FloatT>& f);

Effects: Reads a float from the std::istream and assigns it to the given ts::floating_point. \module types \output_section Input/output

Output operator type_safe::operator<<

template <typename Char, class CharTraits, typename FloatT>
std::basic_ostream<Char, CharTraits>& operator<<(std::basic_ostream<Char, CharTraits>& out, const floating_point<FloatT>& f);

Effects: Converts the given ts::floating_point to the underlying floating point and writes it to the std::ostream. \module types